#ifndef AGENT_H
#define AGENT_H
#include <string>
#include <iostream>
#include <queue>
#include "parameters.hpp"
#include "utils.hpp"
using namespace zhnmat;
using namespace std;
typedef std::vector<double>  vecdble;

class Agent {
public:
    Agent() {};
    void Init() {
        csid = rand() % feasibleStrategy.size();  // 随机选择一个可行策略序号
        nsid = feasibleStrategy[csid];  // 得到该策略的策略编号
        Update();
    }
    void Update() {
        csid = nsid;
        cstrategy = SID_to_ImplementStrategy(csid);  // 计算执行策略
        ccost = Strategy_Cost(cstrategy);  // 计算代价
    }
    // 根据策略编号计算执行策略
    // 例如策略编号为22，即 sid=0b10110，代入执行策略 ___0_0_000 得到 1010100000 即 672
    // uint32_t test = stlt[0].SID_to_ImplementStrategy(22);  // test=672
    uint32_t SID_to_ImplementStrategy(uint32_t sid) {
        uint32_t ans = 0;
        bool b;
        for (int i=0, cnt=0; i<M; i++) {
            if (!((1 << i) & feasibleTask)) continue;
            b = (1 << cnt) & sid;
            if (b) ans |= b << i;
            cnt++;
        }
        return ans;
    }
    // 根据完整策略计算策略编号
    // 完整策略是由{-1,0,1}组成的一个M行1列的矩阵，-1表示无法完成此任务，1表示执行此任务，0表示不执行此任务
    // uint32_t test = stlt[0].TotalStrategy_to_SID(Mat(vecdble{1,0,1,-1,1,-1,0,-1,-1,-1}));
    // test=0b10110=22
    uint32_t TotalStrategy_to_SID(Mat s) {
        uint32_t ans = 0;
        for (int i=0; i<M; i++) {
            if (!((1 << (M-1-i)) & feasibleTask)) continue;
            ans |= (s.at(i, 0)==1);
            ans <<= 1;
        }
        return ans >> 1;
    }
    // 计算当前个体采取给定执行策略的任务总代价
    double Strategy_Cost(uint32_t ims) {
        double c = 0;  // 观测代价
        for (int i = 0; i < M; i++)
            c += matC.at(M-1-i, 0) * bool((1<<i) & ims);
        double d = 0, dpre = 0;  // 总侧摆代价、前一个侧摆代价
        for (int i = 0; i < M; i++) {
            if (!((1<<(M-1-i)) & ims)) continue;
            d += abs(matD.at(i, 0) - dpre);
            dpre = matD.at(i, 0);
        }
        return c + d*SWAY_COEFF;
    }
    int id = -1;
    double ccost;  // 当前任务总代价
    double regret;  // 遗憾值
    Mat matC;  // 每个任务的观测代价
    Mat matD;  // 每个任务的侧摆角
    vector<uint32_t> feasibleStrategy;  // 每个卫星的可执行策略编号
    // 下列数据为按位运算变量，从高位开始
    uint32_t csid, nsid, bestsid;  // 当前策略编号，下一个策略编号，局部最优策略编号
    uint32_t cstrategy;  // 当前执行策略，1表示执行此任务，0表示不执行此任务
    uint32_t neighbor=0;  // 每个卫星的邻居集
    uint32_t feasibleTask=0;  // 每个卫星的可执行任务编号
};

#endif // AGENT_H
